package com.blue.base.common.jwt;

import lombok.extern.slf4j.Slf4j;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * Rsa非对称加密工具【私钥加密，公钥解密】
 *
 * @author liulei
 * @version 1.0
 */
@Slf4j
public class RsaKeyUtil {

    public static KeyPair keyPair;

    public static KeyPair getKeyPair() {
        return keyPair;
    }

    static {
        KeyPairGenerator keyPairGenerator = null;
        try {
            keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        SecureRandom secureRandom = new SecureRandom(JwtConfig.RAS_SALT.getBytes());
        keyPairGenerator.initialize(1024, secureRandom);
        keyPair = keyPairGenerator.genKeyPair();
    }

    /**
     * 获取公钥
     *
     * @param publicKey 根据加密字节码获取公钥
     */
    public static PublicKey getPublicKey(byte[] publicKey) throws Exception {
        X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKey);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(spec);
    }

    /**
     * 获取密钥
     *
     * @param privateKey 根据加密字节码获取公钥
     */
    public static PrivateKey getPrivateKey(byte[] privateKey) throws Exception {
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(spec);
    }

    /**
     * 根据文件获取公钥
     *
     * @param filename 公钥文件名称
     */
    public static PublicKey getPublicKey(String filename) throws Exception {
        InputStream resourceAsStream = Class.forName(RsaKeyUtil.class.getName()).getClassLoader().getResourceAsStream(filename);
        DataInputStream dis = new DataInputStream(resourceAsStream);
        byte[] keyBytes = new byte[resourceAsStream.available()];
        dis.readFully(keyBytes);
        dis.close();
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(spec);
    }

    /**
     * 根据文件获取密钥
     *
     * @param filename 私钥文件名称
     */
    public static PrivateKey getPrivateKey(String filename) throws Exception {
        InputStream resourceAsStream = Class.forName(RsaKeyUtil.class.getName()).getClassLoader().getResourceAsStream(filename);
        DataInputStream dis = new DataInputStream(resourceAsStream);
        byte[] keyBytes = new byte[resourceAsStream.available()];
        dis.readFully(keyBytes);
        dis.close();
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePrivate(spec);
    }

    /**
     * 生成公钥和私钥必须的字节码信息
     */
    public static Map<String, byte[]> generateKey() throws NoSuchAlgorithmException {
        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
        Map<String, byte[]> map = new HashMap<>(2);
        map.put("pub", publicKeyBytes);
        map.put("pri", privateKeyBytes);
        return map;
    }

    /**
     * 字节转字符串
     */
    public static String toHexString(byte[] source) {
        return (new BASE64Encoder()).encodeBuffer(source);
    }

    /**
     * 字符串转字节
     */
    public static final byte[] toBytes(String source) throws IOException {
        return (new BASE64Decoder()).decodeBuffer(source);
    }
}
